package com.wit.witmg.util;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @todo: add config option to this class
 */

@SuppressWarnings("unchecked")
public final class DateUtil {

    public static final long SECOND  = 1000;
    public static final long MINUTE  = SECOND * 60;
    public static final long HOUR    = MINUTE * 60;
    public static final long DAY     = HOUR * 24;
    public static final long WEEK    = DAY * 7;
    public static final long YEAR    = DAY * 365; // or 366 ???

    /**
     * This is the time difference between GMT time and Vietnamese time
     */
    public static final long GMT_VIETNAM_TIME_OFFSET = HOUR * 7;

    /**
     * RFC 822 date format, for RSS 2.0
     * Sat, 07 Sep 2002 00:00:01 GMT
     */
    public static final String RFC_822_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss Z";

    /**
     * ISO 8601 [W3CDTF] date format
     * 2005-06-05T14:52:57EDT
     * Note: not sure Z or z is correct
     */
    public static final String ISO_8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZ";

    /**
     * UTC style date format
     */
    public static final String UTC_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
    
    public static final String COMMON_FORMAT = "yyyy-MM-dd HH:mm:ss";
    /**
     * This is the time difference between GMT time and SERVER time
     */
    //private static long SERVER_TIME_OFFSET = HOUR * (new DateOptions()).serverHourOffset;

    private static DateFormat ddMMyyyyFormat = new SimpleDateFormat("dd/MM/yyyy");
    private static DateFormat yyyyMMddFormat = new SimpleDateFormat("yyyy-MM-dd");
    private static DateFormat rfc822Format = new SimpleDateFormat(RFC_822_DATE_FORMAT, Locale.US);
    private static DateFormat iso8601Format = new SimpleDateFormat(ISO_8601_DATE_FORMAT, Locale.US);
    private static DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.DEFAULT);
    private static DateFormat datetimeFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT);
    private static DateFormat viDateFormat = DateFormat.getDateInstance(DateFormat.DEFAULT, new Locale("vi", "VN"));
    private static DateFormat viDatetimeFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, new Locale("vi", "VN"));
    private static DateFormat headerTimeFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
    //private static DateFormat utcFormat = new SimpleDateFormat(UTC_DATE_FORMAT);

    static {
        TimeZone gmt = TimeZone.getTimeZone("GMT");
        headerTimeFormat.setTimeZone(gmt);
    }

    /**
     * private constructor
     */
    private DateUtil() {// prevent instantiation
    }

    public static synchronized String getDateDDMMYYYY(Date date) {
        return ddMMyyyyFormat.format(date);
    }

    public static synchronized String getDateYYYYMMDD(Date date) {
        return yyyyMMddFormat.format(date);
    }

    public static synchronized String getDateRFC822(Date date) {
        return rfc822Format.format(date);
    }

    public static synchronized String getDateISO8601(Date date) {
        String formattedDate = iso8601Format.format(date);
        int length = formattedDate.length();
        if (length > 2) {
            return new StringBuffer(64).append(formattedDate.substring(0, length - 2)).append(":").append(formattedDate.substring(length - 2)).toString();
        }
        return formattedDate;
    }

    public static synchronized String getHTTPHeaderTime(Date date) {
        return headerTimeFormat.format(date);
    }

    public static synchronized String formatDate(Date date) {
        return dateFormat.format(date);
    }

    public static synchronized String formatDateTime(Date date) {
        return datetimeFormat.format(date);
    }

    public static synchronized String formatViDate(Date date) {
        return viDateFormat.format(date);
    }

    public static synchronized String formatViDateTime(Date date) {
        return viDatetimeFormat.format(date);
    }


    public static Date getVietnamDateFromGMTDate(Date date) {
        return new Date(date.getTime() + GMT_VIETNAM_TIME_OFFSET);
    }

    /* Note that Timestamp is extended from Date
    public static Date getVietnamTimestampFromGMTTimestamp(Timestamp date) {
        return new Timestamp(date.getTime() + GMT_VIETNAM_TIME_OFFSET);
    }*/

    public static Date convertGMTDate(Date gmtDate, double hourOffset) {
        return new Date(gmtDate.getTime() + (long)(hourOffset*HOUR));
    }

    public static Timestamp convertGMTTimestamp(Timestamp gmtTimestamp, double hourOffset) {
        return new Timestamp(gmtTimestamp.getTime() + (long)(hourOffset*HOUR));
    }

    public static Timestamp getCurrentGMTTimestampExpiredYear(int offsetYear) {
        //return new Timestamp(System.currentTimeMillis() + offsetYear*(365*24*60*60*1000));
        Calendar now = Calendar.getInstance();
        now.add(Calendar.YEAR, offsetYear);
        return new Timestamp(now.getTime().getTime());
    }

    public static Timestamp getCurrentGMTTimestampExpiredMonth(int offsetMonth) {
        Calendar now = Calendar.getInstance();
        now.add(Calendar.MONTH, offsetMonth);
        return new Timestamp(now.getTime().getTime());
    }

    public static Timestamp getCurrentGMTTimestampExpiredDay(int offsetDay) {
        Calendar now = Calendar.getInstance();
        now.add(Calendar.DATE,offsetDay);
        return new Timestamp(now.getTime().getTime());
    }

    public static String format(Date date, String pattern) {
        DateFormat formatter = new SimpleDateFormat (pattern, Locale.US);
        return formatter.format(date);
    }

    public static String formatDuration(long duration, String pattern) {
        DurationFormater time = new DurationFormater(duration, pattern);
        return time.toString();
    }

    public static String formatDuration(long duration) {
        DurationFormater time = new DurationFormater(duration, null);
        return time.toString();
    }

    

    /**
     * �õ�ĳ��΢����(����1970.1.1 00:00:00��΢��ֵ)��ʾ����ʱ���е�ʱ�䣬ʱ���ʽΪ��HH:mm:ss�� ,���磺"10:23:01" ��
     * @param dateTime
     * @return
     */
    public final static String getSimpleTime(long dateTime) {
        Date date = new Date(dateTime);
        return formatDate(date, "HH:mm:ss");
    }
    
    /**
     * �õ�һ�������м򵥸�ʽ(��ʽΪ��HH:mm:ss�� ,���磺"10:23:01")��ʱ��
     * @param date
     * @return
     */
    public final static String getSimpleTime(Date date) {
        return formatDate(date, "HH:mm:ss");
    }
    
    /**
     * �õ�һ�������м򵥸�ʽ(��ʽΪ��yyyyMMdd�� ,���磺"20040101")��������
     * @param date
     * @return
     */
    public final static String getSimpleDate(Date date) {
        return formatDate(date, "yyyyMMdd");
    }
    
    /**
     * �õ���ǰʱ�䣬��ʽΪpattern������HH:mm:ss�ȡ�
     * @param pattern String
     * @return String
     * @deprecated
     */
    public final static String getDateTime(Date date, String pattern) {
        SimpleDateFormat format = new SimpleDateFormat(pattern);
        return format.format(date);
    }
    /**
     * ��ʽ                                ʾ��
     "dd/MMM/yyyy"                     06/Mar/1974
     "dd-MM-yyyy"                      06-03-1974
     "dd MMMMMMMMM yyyy"               06 March 1974
     "EEEEEEEEE, MMMMMMMMM dd, yyyy"   Wednesday, March 06, 1974
     ��Ч��SimpleDateFormat��ʾ��ʽ
     ��B��SimpleDateFormat�����������?
     y   year
     M   month in year
     d   day in month
     D   day in year
     w   week in year
     W   week in month
     E   day in week
     
     * @param date
     * @param format
     * @return
     */
    public static String formatDate(Date date, String format) {
    	if(date==null){
    		return "";
    	}
        SimpleDateFormat formatter = new SimpleDateFormat(format);
        return formatter.format(date);
    }
    
    /**
     * �õ���ǰ�����ڣ��Լ򵥸�ʽ����ʽΪ��yyyyMMdd�� ,���磺"20040101"��
     * @return
     */
    public final static String getCurSimpleDate(){
        Calendar cal = Calendar.getInstance();
        return getSimpleDate(cal.getTime());
    }
    
    /**
     * �õ���ǰ�����ڣ��Ը�ʽ����ʽΪ��yyyy-MM-dd�� ,���磺"2004-01-01"��
     * @return
     */
    public final static String getCurDate(){
    	return getDateYYYYMMDD(new Date());
    }
    
    /**
     * �õ���ǰ�����ڣ��Ը�ʽ����ʽΪ��yyyy-MM-dd�� ,���磺"2004-01-01 12:11:12"��
     * @return
     */
    public final static String getCurDateTime(){
    	return formatDate(new Date(),COMMON_FORMAT);
    }
    
    
    /**
     * �õ���ǰ�����ڣ��Լ򵥸�ʽ����ʽΪ��yyyyMMdd�� ,���磺"20040101"��
     * @return
     */
    public final static Integer getCurSimpleDateIntValue(){       
        return new Integer(getCurSimpleDate());
    }
    
    
    
    /**
     * �õ���ǰ��ʱ�䣬�Լ򵥸�ʽ����ʽΪ��HH:mm:ss�� ,���磺"10:23:01"��
     * @return
     */
    public final static String getCurSimpleTime(){
        Calendar cal = Calendar.getInstance();
        return getSimpleTime(cal.getTime());
    }
    
    /**
     * �õ���ǰ����ݣ���ʽΪ"yyyy",����"2005"
     * @return
     */
    public final static String getCurSimpleYear(){
        Calendar cal = Calendar.getInstance();
        return formatDate(cal.getTime(), "yyyy");
    }
    
    /**
     * �õ���ǰ���·ݣ���ʽΪ"MM",����"12"
     * @return
     */  
    public final static String getCurSimpleMonth(){
        Calendar cal = Calendar.getInstance();
        return formatDate(cal.getTime(), "MM");
    }
 
    /**
     * �õ���ǰ�ڼ��죬��ʽΪ"dd",����"02"
     * @return
     */  
    public final static String getCurSimpleDay(){
        Calendar cal = Calendar.getInstance();
        return formatDate(cal.getTime(), "dd");
    }
    
    /**
     * �õ���ǰ����ݣ���ʽΪ"yyyy",����"2005"
     * @return
     */
    public final static Integer getCurSimpleYearIntValue(){
//        Calendar cal = Calendar.getInstance();
        return new Integer(getCurSimpleYear());
    }
    
    /**
     * 8λ����ת��λ10λ������
     * @return
     */
    public final static String date8to10(String date8) {
        if (date8 != null && date8.length() == 8) {
            StringBuffer sb = new StringBuffer(date8);
            sb.insert(6, "-");
            sb.insert(4, "-");
            return sb.toString();
        }
        else {
            return date8;
        }
    }

  /**
   * 10λ����ת��λ8λ������
   * @param date10
   * @return
   */
  public final static String date10to8(String date10) {
    String Date8 = "";
    StringTokenizer datest = new StringTokenizer(date10, "-");
    String datetmp = "";
    while (datest.hasMoreElements()) {
      datetmp = datest.nextToken().trim();
      if (datetmp.length() == 1) {
        datetmp = "0" + datetmp;
      }
      Date8 += datetmp;
    }
    return Date8;
  }
  
  /**
   * �õ�Ĭ�ϵ��������ڣ���"2005-����-07 ������"
   * @return
   */
  public static String getCnDate() {    
      return formatDate(Calendar.getInstance(Locale.CHINA).getTime(), "yyyy-MMM-dd EEE");
  }
  
  /**
   * �õ���������,��"2005��7��7��"
   * @param date8
   * @return
   */
  public static String getCn8Date(String date8) {
      if (date8 != null && date8.length() == 8) {
          StringBuffer sb = new StringBuffer(date8);
          sb.insert(8, "��");
          sb.insert(6, "��");
          sb.insert(4, "��");
          if (sb.charAt(8) == '0') {
              sb.deleteCharAt(8);
          }
          if (sb.charAt(5) == '0') {
              sb.deleteCharAt(5);
          }
          return sb.toString();
      }
      else
          return date8;
  }

  /**
   * �õ��������ڣ���"2005��7��7��"
   * @param date8
   * @return
   */
  public static String getCn8Date(int date8) {
      String temp = String.valueOf(date8);
      return getCn8Date(temp);
  }
  
  /**
   * �õ��������ں����ڣ���"2005��7��7�� ������"
   * @param date8
   * @return
   */
  public static String getCnDateAndWeek(String date8) {
      if (date8 != null && date8.length() == 8) {
          StringBuffer sb = new StringBuffer(date8);
          Calendar cal = Calendar.getInstance(Locale.CHINA);
          
          cal.set(Calendar.YEAR, Integer.parseInt(sb.substring(0, 4)));
          cal.set(Calendar.MONTH, Integer.parseInt(sb.substring(4, 6)) - 1);
          cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(sb.substring(6, 8)));
          sb.insert(8, "��");
          sb.insert(6, "��");
          sb.insert(4, "��");
          if (sb.charAt(8) == '0') {
              sb.deleteCharAt(8);
          }
          if (sb.charAt(5) == '0') {
              sb.deleteCharAt(5);
          }
          
          sb.append(" ")
          .append(formatDate(cal.getTime(), "EEE"));
          return sb.toString();
      }
      else
          return date8;
  }
  
  /**
   * �õ��������ں����ڣ���"2005��7��7�� ������"
   * @param date8
   * @return
   */
  public static String getCnDateAndWeek(int date8) {
      String temp = String.valueOf(date8);
      return getCnDateAndWeek(temp);
  }

  public static Date getDateFromString(String dateString) {
      DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
      LocalDateTime localDateTime = LocalDateTime.parse(dateString, formatter);
      return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
  }

  
  
    public static void main (String[] agrs) {
        long duration = (long)1000 * 60 * 60 *24 * 130 + (long)1000 * 60 * 80;
        System.out.println(duration);
        System.out.println("Duration of " + duration + " duration = " + formatDuration(duration));
        Date date = new Date();
        System.out.println(" Date is " + DateUtil.getDateISO8601(date));
        System.out.println(" Date is " + DateUtil.getDateDDMMYYYY(date));
        System.out.println(" Date is " + DateUtil.getDateRFC822(date));
        System.out.println(" Date is " + DateUtil.getSimpleTime(date));
        System.out.println(" Date is " + DateUtil.getVietnamDateFromGMTDate(date));
        
        System.out.println(" Date is " + DateUtil.getCurDate());
        System.out.println(" Date is " + DateUtil.getCurDateTime());
    }
}

